#!/usr/bin/env sh

# ========== Step 1: Command Line Parameters ========== #
ONLY_LEGION=$1  # 0: Both AFLNet and AFLNet_Legion; 1: Just AFLNet_Legion
PRE_RESULTS=$2  # Previous csv results (e.g. AFLNet) to reuse
TIME_MINUTE=$3  # Experiment time in minutes
LOG_LVL=$4      # Log level
IGN_AST=$5      # Ignore assertions
FUZZ_M3=$6      # Fuzz M3
RHO=$7          # Rho
SUBJECT=$8      # Experiment target
TREE_DP=105       # Log tree depth
PROFUZZBENCH=$(git rev-parse --show-toplevel)

date # Log the starting time

TIME_STAMP=$(date +"%Y-%m-%d-%H=%M=%S")  # Experiment starting time
if [ "${ONLY_LEGION}" = "1" ]; then
  RESULT_DIR="${SUBJECT}_${TIME_MINUTE}MIN_ONLY_AT${TIME_STAMP}"
else
  RESULT_DIR="${SUBJECT}_${TIME_MINUTE}MIN_BOTH_AT${TIME_STAMP}"
fi
RESULT_DIR="${PROFUZZBENCH}/Records/${RESULT_DIR}"
mkdir -p "${RESULT_DIR}" # Where to save experiment results
echo "Results directory: ${RESULT_DIR}" # Confirm the directory to save results


MESSAGE="Duration: ${TIME_MINUTE}min; Log level:${LOG_LVL}; RHO: ${RHO}"

if [ "${IGN_AST}" = "1" ]; then
  MESSAGE="${MESSAGE}  Ignore assertions: True;"
else
  MESSAGE="${MESSAGE}  Ignore assertions: False;"
fi

if [ "${FUZZ_M3}" = "1" ]; then
  MESSAGE="${MESSAGE}  Fuzz M3: True;"
else
  MESSAGE="${MESSAGE}  Fuzz M3: False;"
fi

if [ "${ONLY_LEGION}" = "1" ]; then
  MESSAGE="${MESSAGE}  Legion Only: True;"
else
  MESSAGE="${MESSAGE}  Legion Only: False;"
fi
echo "${MESSAGE}"

AFLNet_Legion_VERSION="AFLNet_Legion Version: $(docker run --cpus=1 -it donggeliu/"${SUBJECT}" \
  /bin/bash -c 'cd aflnet_legion; git --no-pager log -1 --format=%ad')"
echo "${AFLNet_Legion_VERSION}"


# ========== Step 2: Prepare Fuzzing Parameters ========== #
TIME_SECONDS=$((TIME_MINUTE * 60))

LEGION_PARAMS="-l ${LOG_LVL} -p ${TREE_DP} -r ${RHO}"
if [ "${IGN_AST}" = "1" ]; then
  LEGION_PARAMS="${LEGION_PARAMS} -a"
fi
if [ "${FUZZ_M3}" = "1" ]; then
  LEGION_PARAMS="${LEGION_PARAMS} -z"
fi

# Fuzzing options
if [ "${SUBJECT}" = "lightftp" ]; then
  AFLNET_OPTIONS="\"-P FTP -D 10000 -q 3 -s 3 -E -K -c ./ftpclean.sh\""
  LEGION_OPTIONS="\"${LEGION_PARAMS} -P FTP -D 10000 -q 4 -s 4 -E -K -c ./ftpclean.sh\""
  OUTDIR_PARENT="/home/ubuntu/experiments/LightFTP/Source/Release"
elif  [ "${SUBJECT}" = "proftpd" ]; then
  AFLNET_OPTIONS="\"-t 1000+ -m none -P FTP -D 10000 -q 3 -s 3 -E -K -c clean\""
  LEGION_OPTIONS="\"${LEGION_PARAMS} -t 1000+ -m none -P FTP -D 10000 -q 4 -s 4 -E -K -c clean\""
  OUTDIR_PARENT="/home/ubuntu/experiments/proftpd"
elif  [ "${SUBJECT}" = "openssl" ]; then
  AFLNET_OPTIONS="\"-P TLS -D 10000 -q 3 -s 3 -E -K -R -W 100\""
  LEGION_OPTIONS="\"${LEGION_PARAMS} -P TLS -D 10000 -q 4 -s 4 -E -K -R -W 100\""
  OUTDIR_PARENT="/home/ubuntu/experiments/openssl"
elif  [ "${SUBJECT}" = "openssh" ]; then
  AFLNET_OPTIONS="\"-P SSH -D 10000 -q 3 -s 3 -E -K -W 10\""
  LEGION_OPTIONS="\"${LEGION_PARAMS} -P SSH -D 10000 -q 4 -s 4 -E -K -W 10\""
  OUTDIR_PARENT="/home/ubuntu/experiments/openssh"
elif  [ "${SUBJECT}" = "exim" ]; then
  AFLNET_OPTIONS="\"-P SMTP -D 10000 -q 3 -s 3 -E -K -W 100\""
  LEGION_OPTIONS="\"${LEGION_PARAMS} -P SMTP -D 10000 -q 4 -s 4 -E -K -W 100\""
  OUTDIR_PARENT="/home/ubuntu/experiments/exim"
elif  [ "${SUBJECT}" = "live555" ]; then
  AFLNET_OPTIONS="\"-P RTSP -D 10000 -q 3 -s 3 -E -K -R\""
  LEGION_OPTIONS="\"${LEGION_PARAMS} -P RTSP -D 10000 -q 4 -s 4 -E -K -R\""
  OUTDIR_PARENT="/home/ubuntu/experiments/live555/testProgs"
else
  echo "Invalid subject: ${SUBJECT}"
  exit 1
fi


# ========== Step 3: Run Fuzzing ========== #
## Confirm the experiment duration
echo "Fuzzing time     : ${TIME_SECONDS} seconds"
if [ "${ONLY_LEGION}" -eq "0" ]; then
  profuzzbench_exec_common.sh donggeliu/"${SUBJECT}" 4 "${RESULT_DIR}" aflnet out-"${SUBJECT}"-aflnet \
    "${AFLNET_OPTIONS}" "${TIME_SECONDS}" 5 "${OUTDIR_PARENT}" &
  profuzzbench_exec_common.sh donggeliu/"${SUBJECT}" 4 "${RESULT_DIR}" aflnet_legion out-"${SUBJECT}"-aflnet_legion \
    "${LEGION_OPTIONS}" "${TIME_SECONDS}" 5 "${OUTDIR_PARENT}" &
  wait
else
   profuzzbench_exec_common.sh donggeliu/"${SUBJECT}" 4 "${RESULT_DIR}" aflnet_legion out-"${SUBJECT}"-aflnet_legion \
    "${LEGION_OPTIONS}" "${TIME_SECONDS}" 5 "${OUTDIR_PARENT}" &
   wait
fi


# ========== Step 4: Collect the results ========== #
(
  cd "${RESULT_DIR}" || exit
  if [ "${ONLY_LEGION}" -eq "1" ]; then
    echo "Reuse previous results at ../${PRE_RESULTS}/results.csv"
    cp "../${PRE_RESULTS}/results.csv" .
  else
    profuzzbench_generate_csv.sh "${SUBJECT}" 4 aflnet results.csv 0
  fi
  profuzzbench_generate_csv.sh "${SUBJECT}" 4 aflnet_legion results.csv 1 
)


# ========== Step 5: Plot the results ========== #
(
  cd "${RESULT_DIR}" || exit
  echo "Plotting time: ${TIME_MINUTE} minutes"

  profuzzbench_plot.py -i results.csv -p "${SUBJECT}" -r 4 -c "${TIME_MINUTE}" -s 1 -o "${SUBJECT}_${TIME_STAMP}.png" \
    -m "${MESSAGE}" -v "${AFLNet_Legion_VERSION}"
)

# ========== Step 6: Save the stats and errors ========== #
cp "status/stats_${TIME_STAMP}" "${RESULT_DIR}"
cp "status/error_${TIME_STAMP}" "${RESULT_DIR}"

